Skip to content

Add colorblind mode setting#1545

Open
TimCrooker wants to merge 5 commits intopingdotgg:mainfrom
TimCrooker:feat/colorblind-diff-colors
Open

Add colorblind mode setting#1545
TimCrooker wants to merge 5 commits intopingdotgg:mainfrom
TimCrooker:feat/colorblind-diff-colors

Conversation

@TimCrooker
Copy link
Copy Markdown

@TimCrooker TimCrooker commented Mar 29, 2026

What Changed

Added an opt-in Colorblind mode toggle in Settings > General. When enabled, all places where red and green appear side by side to distinguish additions from deletions switch to blue/orange instead.

This uses a CSS-first approach: toggling a colorblind-mode class on :root and defining scoped overrides in index.css. This is the same pattern as the high-contrast mode proposal in #1284, and both can coexist cleanly (:root.colorblind-mode.high-contrast just applies both rule sets).

What colorblind mode is NOT

It is not a global theme override. --success and --destructive are intentionally left untouched at the root level. Red is fine for error messages, delete buttons, and warnings because those don't appear next to green. The problem is specifically red next to green in comparative contexts (additions vs deletions), so the override is scoped only to those elements.

Areas covered

  • Diff panel -- line backgrounds, emphasis highlights, and -N/+N header stats (via @pierre/diffs CSS variable overrides)
  • DiffStatLabel -- the +additions / -deletions text in chat messages
  • GitActionsControl -- per-file and total +insertions / -deletions in the commit dialog

Color palette

From GitHub's Primer design system (@primer/primitives diffBlob tokens), the most widely deployed colorblind-friendly diff palette in production.

Addition (blue) Deletion (orange)
Light #0969da #bc4c00
Dark #388bfd #db6d28

References:

Why

I'm colorblind. Red and green look the same to me, which makes diffs and stats hard to read.

Closes #1537

Compatibility with #1284

This PR follows the exact same architecture as the high-contrast mode proposal:

  • Root CSS class toggle (colorblind-mode class on <html>)
  • All color overrides in index.css (single source of truth)
  • Early sync read in main.tsx to prevent FOUC
  • Runtime sync via useEffect in the root route
  • Both settings compose naturally as independent root classes

A future unified appearance system would just manage which root classes are active.

UI Changes

Settings toggle (off by default):

Screenshot 2026-03-29 at 12 49 17 PM Screenshot 2026-03-29 at 12 49 21 PM

Diff panel -- default (red/green) vs colorblind mode (blue/orange):

Screenshot 2026-03-29 at 12 50 06 PM Screenshot 2026-03-29 at 12 50 15 PM

Diff stats in chat -- default vs colorblind mode:

Screenshot 2026-03-29 at 12 50 26 PM Screenshot 2026-03-29 at 12 50 38 PM

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Low Risk
Low risk UI/accessibility change that primarily adds CSS overrides and a new client-side setting; main risk is minor styling regressions in diff rendering and stat labels.

Overview
Adds an opt-in colorblindMode client setting (default false) with a new toggle in Settings → General, and ensures it’s included in “restore defaults” dirty-state labeling.

Implements a CSS-first blue/orange palette by toggling a colorblind-mode class on :root (applied on startup and kept in sync at runtime), updates diff rendering (DiffPanel) to swap @pierre/diffs addition/deletion variables based on the setting, and standardizes diff stat coloring via new .diff-stat-addition / .diff-stat-deletion classes used in chat and the commit dialog.

Written by Cursor Bugbot for commit 623d6ff. This will update automatically on new commits. Configure here.

Note

Add colorblind mode setting that switches diff colors to blue/orange

  • Adds a colorblindMode boolean to ClientSettingsSchema and exposes a toggle in the General settings panel via SettingsPanels.tsx.
  • Applies a colorblind-mode class to document.documentElement on startup via main.tsx and keeps it in sync at runtime via a new ColorblindModeSync component in __root.tsx.
  • Adds CSS variables and .diff-stat-addition/.diff-stat-deletion classes in index.css that switch from green/red to blue/orange when the colorblind-mode class is present.
  • Updates DiffPanel.tsx, DiffStatLabel.tsx, and GitActionsControl.tsx to use the new colorblind-aware color classes.

Macroscope summarized 623d6ff.

Toggle a root CSS class to swap red/green with blue/orange in diff
contexts (panel backgrounds, header stats, inline stat labels). Colors
from GitHub Primer's @primer/primitives diffBlob tokens. Follows the
same root-class pattern as the high-contrast mode proposal (pingdotgg#1284).

Closes pingdotgg#1537
Copilot AI review requested due to automatic review settings March 29, 2026 17:19
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 29, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4a96da5b-2068-4de5-a6f5-e2ecc2cc478b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 29, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in Colorblind mode client setting that swaps red/green comparative diff colors to a blue/orange palette by toggling a root CSS class and applying scoped CSS/variable overrides.

Changes:

  • Extend client settings schema with colorblindMode (default false) and add contract/unit coverage.
  • Apply colorblind-mode root class at startup and keep it in sync at runtime via the root route.
  • Update diff/stat UI to use new CSS hooks and update diff panel CSS variable overrides when enabled.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/contracts/src/settings.ts Adds colorblindMode to ClientSettingsSchema with a decoding default.
packages/contracts/src/settings.test.ts Verifies DEFAULT_CLIENT_SETTINGS.colorblindMode defaults to false.
apps/web/src/hooks/useSettings.ts Adds helpers to toggle the root class and read the persisted value early.
apps/web/src/hooks/useSettings.test.ts Ensures legacy migration patch does not attempt to migrate colorblindMode.
apps/web/src/main.tsx Applies colorblind mode before first React render to avoid a flash.
apps/web/src/routes/__root.tsx Keeps the root class synced with live settings via an effect.
apps/web/src/index.css Defines blue/orange variables under :root.colorblind-mode and stat color classes.
apps/web/src/components/settings/SettingsPanels.tsx Adds Settings > General toggle + restore-defaults detection for the new setting.
apps/web/src/components/chat/DiffStatLabel.tsx Uses new stat CSS classes so the palette can be overridden by colorblind mode.
apps/web/src/components/GitActionsControl.tsx Uses new stat CSS classes for per-file/total insertions/deletions.
apps/web/src/components/DiffPanel.tsx Dynamically switches @pierre/diffs override variables based on the setting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Fix diff-stat default colors to use --color-success/--color-destructive
(matching text-success/text-destructive) instead of the -foreground
variants. Add try/catch around getStoredColorblindMode to prevent
malformed localStorage from crashing startup. Merge duplicate imports.
@TimCrooker
Copy link
Copy Markdown
Author

@juliusmarminge Rewrote this to follow the same root-class pattern as #1284. Toggles colorblind-mode on :root, all overrides in index.css, early sync read to prevent FOUC, runtime sync in the root route. Both compose cleanly as independent root classes.

The one intentional difference: colorblind mode only overrides diff-specific elements, not --success/--destructive globally. Red is fine for errors and delete buttons on their own. The problem is only when red and green appear side by side in comparative contexts like diffs.

TimCrooker and others added 2 commits March 29, 2026 14:55
Resolve modify/delete conflict on packages/contracts/src/settings.test.ts
by accepting main's deletion — the file was removed in pingdotgg#1538 and the
colorblind default is covered by the schema itself.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add colorblind-friendly diff colors setting

2 participants